package com.cmccgz.udacs_landlord_webapp.main.unlock;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;

import com.cmccgz.baselibrary.utils.ByteHexStringUtils;
import com.cmccgz.udacs_landlord_webapp.base.AppConfig;
import com.orhanobut.logger.Logger;

import java.util.UUID;

/**
 * @author: Huang
 * @Descripion:
 * @date 2017/5/9 09:50
 */

public class BluetoothLeNewService extends Service {

    private final static String TAG = BluetoothLeNewService.class.getSimpleName();

    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothGatt bluetoothGatt;

    public final static String ACTION_GATT_CONNECTED = "com.gzcmcc.bluetooth.le.ACTION_GATT_CONNECTED";
    public final static String ACTION_GATT_DISCONNECTED = "com.gzcmcc.bluetooth.le.ACTION_GATT_DISCONNECTED";
    public final static String ACTION_GATT_SERVICES_DISCOVERED_FAILED = "com.gzcmcc.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED_FAILED";
    public final static String ACTION_GATT_DESCRIPTOR_WRITE_SUCCESS = "com.gzcmcc.bluetooth.le.ACTION_GATT_DESCRIPTOR_WRITE_SUCCESS";
    public final static String ACTION_GATT_DESCRIPTOR_WRITE_FAILED = "com.gzcmcc.bluetooth.le.ACTION_GATT_DESCRIPTOR_WRITE_FAILED";
    public final static String ACTION_GATT_CHARACTERISTIC_WRITE_FAILED = "com.gzcmcc.bluetooth.le.ACTION_GATT_CHARACTERISTIC_WRITE_FAILED";
    public final static String ACTION_DATA_AVAILABLE = "com.gzcmcc.bluetooth.le.ACTION_DATA_AVAILABLE";
    public final static String ACTION_STATE_ON = "com.gzcmcc.bluetooth.le.ACTION_STATE_ON";
    public final static String ACTION_STATE_OFF = "com.gzcmcc.bluetooth.le.ACTION_STATE_OFF";
    public final static String EXTRA_DATA = "com.gzcmcc.bluetooth.le.EXTRA_DATA";


    private BluetoothGattCallback callback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            BluetoothDevice gattDevice = gatt.getDevice();
//            String intentAction;
            if (newState == BluetoothProfile.STATE_CONNECTED) {
//                intentAction = ACTION_GATT_CONNECTED;
//                Intent intent = new Intent(intentAction);
//                intent.putExtra("device", gattDevice);
                broadcastUpdate(ACTION_GATT_CONNECTED);
                Logger.i(gattDevice.getAddress() + "成功连接到GATT服务端");
                //发现设备
                boolean discoverServices = gatt.discoverServices();
                Logger.i("发现设备状态：" + discoverServices);

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
//                intentAction = ACTION_GATT_DISCONNECTED;
//                Intent intent = new Intent(intentAction);
//                intent.putExtra("device", gattDevice);
                Logger.i(gattDevice.getAddress() + "失去GATT服务端的连接");
                broadcastUpdate(ACTION_GATT_DISCONNECTED);
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                BluetoothGattService service = gatt.getService(UUID.fromString(AppConfig.UUID_SERVICE));
                BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(AppConfig.UUID_CHARACTERISTIC));
                setCharacteristicNotification(gatt, characteristic, true);
            } else {
//                Intent intent = new Intent(ACTION_GATT_SERVICES_DISCOVERED_FAILED);
//                intent.putExtra("device",gatt.getDevice());
                broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED_FAILED);
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Logger.e("写入数据成功！");
            } else {
//                Intent intent = new Intent(ACTION_GATT_CHARACTERISTIC_WRITE_FAILED);
//                intent.putExtra("device",gatt.getDevice());
                broadcastUpdate(ACTION_GATT_CHARACTERISTIC_WRITE_FAILED);
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
//                Logger.e("收到消息");
//            BluetoothDevice gattDevice = gatt.getDevice();
            Intent intent = new Intent(ACTION_DATA_AVAILABLE);
//            intent.putExtra(DEVICE_ADDRESS, gattDevice.getAddress());
            final byte[] data = characteristic.getValue();
//                if (data != null && data.length > 0) {
//                    final StringBuilder stringBuilder = new StringBuilder(data.length);
//                    for (byte byteChar : data)
//                        stringBuilder.append(String.format("%02X ", byteChar));
//                    intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
//                }
            String hexString = ByteHexStringUtils.bytesToHexString(data);
            intent.putExtra(EXTRA_DATA, hexString);
            broadcastUpdate(intent);
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Logger.e("descriptor写入成功");
//                Intent intent = new Intent(ACTION_GATT_DESCRIPTOR_WRITE_SUCCESS);
//                intent.putExtra("device",gatt.getDevice());
                broadcastUpdate(ACTION_GATT_DESCRIPTOR_WRITE_SUCCESS);
            } else {
//                Intent intent = new Intent(ACTION_GATT_DESCRIPTOR_WRITE_FAILED);
//                intent.putExtra("device",gatt.getDevice());
                broadcastUpdate(ACTION_GATT_DESCRIPTOR_WRITE_FAILED);
            }
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
    }

    private IBinder mBinder = new LocalBinder();

    public class LocalBinder extends Binder {
        public BluetoothLeNewService getService() {
            return BluetoothLeNewService.this;
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        close();
        return super.onUnbind(intent);
    }

    /**
     * 关闭资源
     */
    private void close() {
        if (bluetoothGatt != null) {
            bluetoothGatt.close();
            bluetoothGatt = null;
        }
    }

    /**
     * 初始化
     *
     * @return
     */
    public boolean initialize() {
        if (mBluetoothManager == null) {
            mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            if (mBluetoothManager == null) {
                Logger.e("无法初始化BluetoothManager");
                return false;
            }
        }

        mBluetoothAdapter = mBluetoothManager.getAdapter();
        if (mBluetoothAdapter == null) {
            Logger.e("无法获得BluetoothAdapter");
            return false;
        }
        return true;
    }

    /**
     * 建立连接
     *
     * @param device 硬件地址集合
     * @return
     */
    public boolean connect(BluetoothDevice device) {
        if (device == null) {
            Logger.w("没有找到设备，无法连接");
            return false;
        }

        if (mBluetoothAdapter == null || TextUtils.isEmpty(device.getAddress())) {
            Logger.w("BluetoothAdapter 没有初始化 或者 物理地址不可用！");
            return false;
        }

        // 尝试重连
        if (bluetoothGatt != null) {
            if (bluetoothGatt.connect()) {
                return true;
            } else {
                return false;
            }
        }

        bluetoothGatt = device.connectGatt(this, false, callback);
        Logger.d("尝试建立新连接");
        return true;
    }


    /**
     * 断开连接
     */
    public void disconnect() {
        if (mBluetoothAdapter == null) {
            Logger.w("BluetoothAdapter 没有初始化");
            return;
        }
        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
            @Override
            public void run() {
                if (bluetoothGatt != null) {
                    bluetoothGatt.disconnect();
                    bluetoothGatt.close();
                    bluetoothGatt = null;
                }
            }
        },150);
    }

    /**
     * 读取characteristic数据
     *
     * @param characteristic
     */
//    public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
//
//        for (BluetoothLeBean bean:leBeanMap.values()){
//            if (mBluetoothAdapter == null){
//                Log.w(TAG, "BluetoothAdapter not initialized");
//                return;
//            }
//            BluetoothGatt gatt = bean.getGatt();
//            if (gatt !=null){
//                gatt.readCharacteristic(characteristic);
//            }
//        }
//
//        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
//            Log.w(TAG, "BluetoothAdapter not initialized");
//            return;
//        }
//        mBluetoothGatt.readCharacteristic(characteristic);
//    }

    /**
     * 写入characteristic数据
     *
     * @param characteristic
     */
    public void writeCharacteristic(BluetoothGattCharacteristic characteristic) {
        if (mBluetoothAdapter == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }

        if (bluetoothGatt != null) {
//            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
//                @Override
//                public void run() {
//                    System.out.println("写入数据");
//                    bluetoothGatt.writeCharacteristic(characteristic);
//                }
//            },15);
            System.out.println("写入数据");
            bluetoothGatt.writeCharacteristic(characteristic);
        }
    }

    /**
     * 设置是否能接收广播
     *
     * @param gatt
     * @param characteristic
     * @param enabled
     */
    public void setCharacteristicNotification(final BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, boolean enabled) {
        if (mBluetoothAdapter == null || gatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        //设置notification
        // TODO: 2017/5/9
        gatt.setCharacteristicNotification(characteristic, enabled);
        final BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                UUID.fromString(AppConfig.UUID_DESCRIPTOR));
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
            @Override
            public void run() {
                gatt.writeDescriptor(descriptor);
            }
        }, 500);

    }

    /**
     * 直接广播更新
     *
     * @param action
     */
    private void broadcastUpdate(final String action) {
        final Intent intent = new Intent(action);
        sendBroadcast(intent);
    }

    private void broadcastUpdate(Intent intent) {
        sendBroadcast(intent);
    }

    /**
     * 根据characteristic广播更新
     *
     * @param action
     * @param characteristic
     */
    private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) {
        final Intent intent = new Intent(action);
        //判断操作
        // TODO: 2017/5/9
        sendBroadcast(intent);
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        close();
    }

    public BluetoothGatt getBluetoothGatt() {
        return bluetoothGatt;
    }
}
